package com.zxx.coolweather._wuguan3_ok;

import org.litepal.util.LogUtil;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Function;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

/**
 * 自定义重试次数（重试拦截器）
 *
 * OkHttp自带retryOnConnectionFailure(true)方法可以实现重试，但是不支持自定义重试次数
 *
 * 使用：
 * new OkHttpClient.Builder().addInterceptor(new RetryInterceptor(3))//重试
 *
 * @author zxx on 2022/1/14
 */
public class RetryInterceptor implements Interceptor {

    public int maxRetry;//最大重试次数
    private int retryNum = 0;//假如设置为3次重试的话，则最大可能请求4次（默认1次+3次重试）

    public RetryInterceptor(int maxRetry) {
        this.maxRetry = maxRetry;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        System.out.println("retryNum=" + retryNum);

        Response response = chain.proceed(request);

        while (!response.isSuccessful() && retryNum < maxRetry) {
            retryNum++;
            System.out.println("retryNum=" + retryNum);

            response = chain.proceed(request);
        }

        return response;
    }


    //如果你是使用OkHttp+Retrofit+RxJava，你也可以使用retryWhen操作符：retryWhen(new RetryWithDelay())来实现重试机制
    class RetryWithDelay implements Function<Observable<? extends Throwable>, Observable<?>> {

        private final int maxRetries;
        private final int retryDelayMillis;
        private int retryCount;

        public RetryWithDelay(int maxRetries, int retryDelayMillis) {
            this.maxRetries = maxRetries;
            this.retryDelayMillis = retryDelayMillis;
        }

        @Override
        public Observable<?> apply(@NonNull Observable<? extends Throwable> observable) throws Exception {
            return observable.flatMap(new Function<Throwable, ObservableSource<?>>() {
                @Override
                public ObservableSource<?> apply(@NonNull Throwable throwable) throws Exception {
                    if (++retryCount <= maxRetries) {
                        // When this Observable calls onNext, the original Observable will be retried (i.e. re-subscribed).
                        System.out.println("get error, it will try after " + retryDelayMillis + " millisecond, retry count " + retryCount);

                        return Observable.timer(retryDelayMillis, TimeUnit.SECONDS);
                    }

                    // Max retries hit. Just pass the error along.
                    return Observable.error(throwable);
                }
            });
        }
    }


}
